package jwt

import (
	"errors"
	"fmt"
	"time"

	"go.uber.org/zap"

	"github.com/golang-jwt/jwt"
)

// 定义 token 生效时间
const TokenExpireOuration = time.Hour * 24 * 265

// 定义秘钥
var mySecret = []byte("abcdefghijklmnopqrstuvwxyz")

// 定义自己的 载体，并继承共有字段， 实现Claims接口
type MyCustomClaims struct {
	UserID   int64  `json:"user_id"`
	Username string `json:"username"`
	jwt.StandardClaims
}

// 封装生成Token的函数
func GenToken(userID int64, username string) (string, error) {
	// Create the Claims
	claims := MyCustomClaims{
		userID,
		username,
		jwt.StandardClaims{
			// 指定过期时间
			ExpiresAt: time.Now().Add(TokenExpireOuration).Unix(),
			// 签发人： 写上项目名
			Issuer: "HdlBluebell",
		},
	}
	// 创建token
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	// 使用指定的secret签名并获得完整的编码后的字符串token
	tokenStr, err := token.SignedString(mySecret)
	fmt.Println("1111", string(mySecret))
	return tokenStr, err
}

// 双刷token
//func GenToken1(userID int64, username string) (aToken, rToken string, err error) {
//	// 1. Create the Claims
//	claims := MyCustomClaims{
//		userID,
//		username,
//		jwt.StandardClaims{
//			// 指定过期时间
//			ExpiresAt: time.Now().Add(TokenExpireOuration).Unix(),
//			// 签发人： 写上项目名
//			Issuer: "HdlBluebell",
//		},
//	}
//	// 2. 创建token
//	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
//	// 使用指定的secret签名并获得完整的编码后的字符串token
//	aToken, err = token.SignedString(mySecret)
//	// 生成 refresh token， 不需要自定义的信息
//	rToken, err = jwt.NewWithClaims(jwt.SigningMethodES256, jwt.StandardClaims{
//		ExpiresAt: time.Now().Add(time.Second * 30).Unix(),
//		Issuer:    "HdlBluebell",
//	}).SignedString(mySecret)
//	// 3.
//	return
//}

// 解析token字符串
func ParseToken(tokenString string) (*MyCustomClaims, error) {
	fmt.Println(string(mySecret))
	// 调用解析函数
	token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
		// 只返回加密的秘钥
		return mySecret, nil
	})
	if err != nil {
		zap.L().Error("pkg.jwt.ParseToken() fail", zap.Error(err))
		fmt.Println(err.Error())
		return nil, err
	}
	// 拿到 MyCustomClaims 类型的结构
	// Claims 接口实现了 Valid() 方法， 对数据进行验证
	if claims, ok := token.Claims.(*MyCustomClaims); ok && token.Valid {
		return claims, nil
	} else {
		return nil, errors.New("invalid token")
	}
}

// 解析 refresh token
//func RefreshToken(aToken, rToken string) (newAToken, newRToken string, err error) {
//	// 1. 解析refresh token， 无效直接返回错误
//	if _, err = jwt.Parse(rToken, func(token *jwt.Token) (interface{}, error) {
//		return []byte("AllYourBase"), nil
//	}); err != nil {
//		return
//	}
//	// 2. 从旧 access token 中解析出claims数据
//	var claims MyCustomClaims
//	_, err := jwt.ParseWithClaims(aToken, &claims, func(token *jwt.Token) (interface{}, error) {
//		return []byte("AllYourBase"), nil
//	})
//	v, _ := err.(*jwt.ValidationError)
//	return
//}
